home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / program / umentilr.lha / Umentiler / source / Umentiler.c < prev   
C/C++ Source or Header  |  1996-01-10  |  24KB  |  1,032 lines

  1. /*************************************************************************
  2.  *
  3.  * Umentiler
  4.  *
  5.  * Copyright ©1995 Lee Kindness cs2lk@scms.rgu.ac.uk
  6.  *
  7.  * Read Umentiler.guide (from the main archive) for distribution details.
  8.  *
  9.  * Umentiler.c
  10.  */
  11.  
  12. /* Includes are kept in gst.c for gst compilation purposes */
  13. #include "gst.c"
  14.  
  15. extern struct ExecBase *SysBase;
  16. extern struct DosLibrary *DOSBase;
  17. extern struct LocaleBase *LocaleBase;
  18.  
  19. /* Revision information */
  20. #include "Umentiler_rev.h"
  21.  
  22. /* Version String */
  23. const char ver[] = VERSTAG;
  24. const char tst[] = "$MOOD: Here is a short story:\n" \
  25.                    "This is the start.\n" \
  26.                    "This is the middle.\n" \
  27.                    "And this is the end!";
  28.  
  29. /*
  30.  * Keep all 'global' vars in a locally allocated and 
  31.  * passed around structure => Gives pure, reentrant code
  32.  * (We get this with SAS anway...)
  33.  */
  34. struct Vars
  35. {
  36.     ULONG              v_Tags_p;
  37.     ULONG              v_Tags_e;
  38.     ULONG              v_Tags_i;
  39.     ULONG              v_BufSize;
  40.     struct Locale     *v_Locale;
  41.     struct LocaleBase *v_LocaleBase;
  42. };
  43.  
  44. /* Prototypes */
  45. STRPTR      strsistr      (STRPTR, STRPTR);
  46. VOID        AddC2Cmd      (STRPTR, char);
  47. VOID        MFPutC        (BPTR, char, BOOL);
  48. VOID        RepMarkers    (struct Vars *, STRPTR, BPTR, BOOL);
  49. VOID        HInsertion    (struct Vars *, BPTR, STRPTR, ULONG);
  50. VOID        HInsertCmd    (struct Vars *, BPTR, STRPTR);
  51. ULONG __asm LFFunc        (register __a0 struct Hook *,
  52.                            register __a2 struct Locale *,
  53.                            register __a1 char);
  54. VOID        HDateCmd      (struct Vars *, BPTR, STRPTR, STRPTR, 
  55.                            LONG, BOOL, BOOL, BOOL);
  56. VOID        HVersionCmd   (struct Vars *, BPTR, STRPTR, BOOL, BOOL, BOOL, BOOL, BOOL);
  57. VOID        HProgramCmd   (struct Vars *, BPTR, STRPTR, BOOL);
  58. VOID        HVarCmd       (BPTR, STRPTR, BOOL, BOOL, BOOL);
  59. VOID        HSetvarCmd    (STRPTR, STRPTR);
  60. VOID        HTagCmd       (struct Vars *, BPTR, STRPTR, STRPTR, BOOL);
  61.  
  62.  
  63. /* Template for all temp file names */
  64. #define TMP_TEMP "T:UXXXXXX.XXX"
  65.  
  66.  
  67. /*************************************************************************
  68.  * strsistr() - returns s if f occurs at the start of s. Case insensitive.
  69.  */
  70.  
  71. STRPTR strsistr(STRPTR s, STRPTR f)
  72. {
  73.     if( s && f )
  74.     {
  75.         BOOL match = TRUE;
  76.         for( ; *s && *f && match; ++s, ++f )
  77.             if( toupper(*s) != toupper(*f) )
  78.                 match = FALSE;
  79.         if( match )
  80.             return( s );
  81.         else
  82.             return( NULL );
  83.     } else
  84.         return( NULL ); 
  85. }
  86.  
  87.  
  88. /*************************************************************************
  89.  * AddC2Cmd() - Add a charcter to the command string
  90.  */
  91.  
  92. VOID AddC2Cmd(STRPTR cmd, char ch)
  93. {
  94.     STRPTR s;
  95.     /* Find the null */
  96.     s = strchr(cmd, '\0');
  97.     /* Add the char */
  98.     *s = ch;
  99.     /*
  100.      * ++s;
  101.      * *s = '\0'
  102.      *
  103.      * (no need, we MEMF_CLEARed it)
  104.      */
  105. }
  106.  
  107.  
  108. /*************************************************************************
  109.  * MFPutC() - Will FPutC if certain conditions.
  110.  */
  111.  
  112. VOID MFPutC(BPTR file, char ch, BOOL nolines)
  113. {
  114.     if( !(nolines && ch == '\n') )
  115.         FPutC(file, ch);
  116. }
  117.  
  118.  
  119. /*************************************************************************
  120.  * HInsertion() - Insert text into the file
  121.  */
  122.  
  123. /* Commands */
  124. #define TXT_INSERT "INSERT"
  125. #define CMD_INSERT 1
  126. #define TXT_DATE "DATE"
  127. #define CMD_DATE 2
  128. #define TXT_VERSION "VERSION"
  129. #define CMD_VERSION 3
  130. #define TXT_PROGRAM "PROGRAM"
  131. #define CMD_PROGRAM 4
  132. #define TXT_VAR "VAR"
  133. #define CMD_VAR 5
  134. #define TXT_SETVAR "SETVAR"
  135. #define CMD_SETVAR 6
  136. #define TXT_TAG "TAG"
  137. #define CMD_TAG 7
  138.  
  139. /* And ReadArg() templates for each */
  140. #define TMP_INSERT "FILE/A"
  141. #define OPT_INSERT_FILE 0
  142. #define TMP_DATE "FROM/K,LF=LOCALEFORMAT/K,F=FORMAT/N/K,NY=NODAY/S,ND=NODATE/S,NT=NOTIME/S"
  143. #define OPT_DATE_FROM 0
  144. #define OPT_DATE_LOCALEFORMAT 1
  145. #define OPT_DATE_FORMAT 2
  146. #define OPT_DATE_NODAY 3
  147. #define OPT_DATE_NODATE 4
  148. #define OPT_DATE_NOTIME 5
  149. #define TMP_VERSION "FROM/A,F=FULL/S,NN=NONAME/S,NV=NOVER/S,ND=NODATE/S,NPD=NOPARSEDATE/S"
  150. #define OPT_VERSION_FROM 0
  151. #define OPT_VERSION_FULL 1
  152. #define OPT_VERSION_NONAME 2
  153. #define OPT_VERSION_NOVER 3
  154. #define OPT_VERSION_NODATE 4
  155. #define OPT_VERSION_NOPARSEDATE 5
  156. #define TMP_PROGRAM "NL=NOLINES/S,CMDLINE/A/F"
  157. #define OPT_PROGRAM_NOLINES 0
  158. #define OPT_PROGRAM_CMDLINE 1
  159. #define TMP_VAR "FROM/A,NL=NEWLINE/S,G=GLOBAL/S,L=LOCAL/S"
  160. #define OPT_VAR_FROM 0
  161. #define OPT_VAR_NEWLINE 1
  162. #define OPT_VAR_GLOBAL 2
  163. #define OPT_VAR_LOCAL 3
  164. #define TMP_SETVAR "NAME/A,TEXT/A/F"
  165. #define OPT_SETVAR_NAME 0
  166. #define OPT_SETVAR_TEXT 1
  167. #define TMP_TAG "TAG/A,FILE/A,NONLCUT/S"
  168. #define OPT_TAG_TAG 0
  169. #define OPT_TAG_NAME 1
  170. #define OPT_TAG_NONLCUT 2
  171.  
  172. /* Maximum number of options */
  173. #define OPT_ALL_MAX (OPT_DATE_NOTIME + 1)
  174. #define NOARG "\n"
  175.  
  176. VOID HInsertion(struct Vars *vars, BPTR destf, STRPTR cmd, ULONG cmdsize)
  177. {
  178.     STRPTR s, arg, temp;
  179.     LONG cnum;
  180.     
  181.     /* Skip any initial white space */
  182.     cmd = stpblk(cmd);
  183.     
  184.     /* skip to the arguments */
  185.     if( arg = strpbrk(cmd, "\t ") )
  186.         arg = stpblk(arg);
  187.     else
  188.         arg = NOARG;
  189.     
  190.     /* What command ? */
  191.     if( s = strsistr(cmd, TXT_INSERT) )
  192.     {
  193.         cnum = CMD_INSERT;
  194.         temp = TMP_INSERT;
  195.     } else if( s = strsistr(cmd, TXT_DATE) )
  196.     {
  197.         cnum = CMD_DATE;
  198.         temp = TMP_DATE;
  199.     } else if( s = strsistr(cmd, TXT_VERSION) )
  200.     {
  201.         cnum = CMD_VERSION;
  202.         temp = TMP_VERSION;
  203.     } else if( s = strsistr(cmd, TXT_PROGRAM) )
  204.     {
  205.         cnum = CMD_PROGRAM;
  206.         temp = TMP_PROGRAM;
  207.     } else if( s = strsistr(cmd, TXT_VAR) )
  208.     {
  209.         cnum = CMD_VAR;
  210.         temp = TMP_VAR;
  211.     } else if( s = strsistr(cmd, TXT_SETVAR) )
  212.     {
  213.         cnum = CMD_SETVAR;
  214.         temp = TMP_SETVAR;
  215.     } else if( s = strsistr(cmd, TXT_TAG) )
  216.     {
  217.         cnum = CMD_TAG;
  218.         temp = TMP_TAG;
  219.     } else
  220.     {
  221.         PrintFault(ERROR_ACTION_NOT_KNOWN, cmd);
  222.         cnum = 0;
  223.         temp = NULL;
  224.         ++vars->v_Tags_i;
  225.     }
  226.     if( cnum && temp && arg )
  227.     {
  228.         struct RDArgs *rda;
  229.         
  230.         /* Add a newline to the end of cmd (for ReadArgs()) */
  231.         if( *cmd != '\n' )
  232.             AddC2Cmd(cmd, '\n');
  233.         
  234.         if( rda = AllocDosObject(DOS_RDARGS, NULL) )
  235.         {
  236.             STRPTR args[OPT_ALL_MAX];
  237.             
  238.             rda->RDA_DAList = NULL;
  239.             rda->RDA_Flags |= RDAF_NOPROMPT;
  240.             rda->RDA_Buffer = NULL;
  241.             rda->RDA_Source.CS_Buffer = arg;
  242.             rda->RDA_Source.CS_Length = strlen(arg);
  243.             rda->RDA_Source.CS_CurChr = 0;
  244.             
  245.             memset(&args, 0, (sizeof(STRPTR) * OPT_ALL_MAX));
  246.             
  247.             /* Parse argumesnts for the option */
  248.             if( ReadArgs(temp, (LONG *)&args, rda) ) 
  249.             {
  250.                 switch( cnum )
  251.                 {
  252.                     case CMD_INSERT :
  253.                         HInsertCmd(vars, destf, args[OPT_INSERT_FILE]);
  254.                         break;
  255.                         
  256.                     case CMD_VERSION :
  257.                         HVersionCmd(vars, destf, args[OPT_VERSION_FROM],
  258.                                      (BOOL)args[OPT_VERSION_FULL],
  259.                                      (BOOL)args[OPT_VERSION_NONAME],
  260.                                      (BOOL)args[OPT_VERSION_NOVER],
  261.                                      (BOOL)args[OPT_VERSION_NODATE],
  262.                                      (BOOL)args[OPT_VERSION_NOPARSEDATE]);
  263.                         break;
  264.                         
  265.                     case CMD_PROGRAM :
  266.                         HProgramCmd(vars, destf, args[OPT_PROGRAM_CMDLINE],
  267.                                            (BOOL)args[OPT_PROGRAM_NOLINES]);
  268.                         break;
  269.                         
  270.                     case CMD_DATE :    
  271.                         HDateCmd(vars, destf, args[OPT_DATE_FROM],
  272.                                               args[OPT_DATE_LOCALEFORMAT],
  273.                                               args[OPT_DATE_FORMAT] ? *((LONG *)args[OPT_DATE_FORMAT]) : 0,
  274.                                         (BOOL)args[OPT_DATE_NODAY],
  275.                                         (BOOL)args[OPT_DATE_NODATE],
  276.                                         (BOOL)args[OPT_DATE_NOTIME]);
  277.                         break;
  278.                     
  279.                     case CMD_VAR :
  280.                         HVarCmd(destf, args[OPT_VAR_FROM],
  281.                                  (BOOL)args[OPT_VAR_NEWLINE],
  282.                                  (BOOL)args[OPT_VAR_GLOBAL],
  283.                                  (BOOL)args[OPT_VAR_LOCAL]);
  284.                         break;
  285.                     
  286.                     case CMD_SETVAR :
  287.                         HSetvarCmd(args[OPT_SETVAR_NAME],
  288.                                    args[OPT_SETVAR_TEXT]);
  289.                         break;
  290.                     
  291.                     case CMD_TAG :
  292.                         HTagCmd(vars, destf, args[OPT_TAG_TAG],
  293.                                 args[OPT_TAG_NAME],
  294.                           (BOOL)args[OPT_TAG_NONLCUT]);
  295.                         break;
  296.                 }
  297.                 ++vars->v_Tags_p;
  298.                 FreeArgs(rda);
  299.             } else
  300.                 ++vars->v_Tags_i;
  301.             FreeDosObject(DOS_RDARGS, rda);
  302.         }
  303.     }
  304.     /* Clear cmd */
  305.     memset(cmd, 0, cmdsize);
  306. }
  307.  
  308.  
  309. /*************************************************************************
  310.  * HInsertCmd() - Handle the INSERT command.
  311.  */
  312.  
  313. VOID HInsertCmd(struct Vars *vars, BPTR destf, STRPTR from)
  314. {
  315.     /* paste a file
  316.      * We simply recurse, call RepMarkers()
  317.      */
  318.     RepMarkers(vars, from, destf, FALSE);
  319. }
  320.  
  321.  
  322. /*************************************************************************
  323.  * HVersionCmd() - Handle the VERSION command.
  324.  */
  325.  
  326. #define VERSION_CMD_1ST_PART "Version "
  327. #define VERSION_CMD_2ND_PART " FULL"
  328. #define VERBUF_SIZE 256
  329. #define STATE_NAME 0
  330. #define STATE_VERSION 1
  331. #define STATE_DATE 2
  332.  
  333. VOID HVersionCmd(struct Vars *vars, BPTR destf, STRPTR from, 
  334.                  BOOL full, BOOL noname,
  335.                  BOOL nover, BOOL nodate, BOOL noparsedate)
  336. {
  337.     STRPTR cmd;
  338.     
  339.     /* Alloc cmd */
  340.     if( cmd = AllocVec(strlen(VERSION_CMD_1ST_PART) +
  341.                        strlen(VERSION_CMD_2ND_PART) +
  342.                        strlen(from) + 1, 0) )
  343.     {
  344.         STRPTR tmpname;
  345.         
  346.         /* build the command line */
  347.         strcpy(cmd, VERSION_CMD_1ST_PART);
  348.         strcat(cmd, from);
  349.         strcat(cmd, VERSION_CMD_2ND_PART);
  350.         
  351.         /* Alloc tmpname */
  352.         if( tmpname = AllocVec(14, 0) )
  353.         {
  354.             strcpy(tmpname, TMP_TEMP);
  355.             mktemp(tmpname);
  356.             if( *tmpname != 0 )
  357.             {
  358.                 BPTR tf;
  359.                 
  360.                 /* Open temp file */
  361.                 if( tf = Open(tmpname, MODE_NEWFILE) )
  362.                 {
  363.                     BPTR inf;
  364.                     
  365.                     /* Change buffer */
  366.                     SetVBuf(tf, NULL, vars->v_BufSize, BUF_FULL);
  367.                     
  368.                     /* Open input file */
  369.                     if( inf = Open("NIL:", MODE_OLDFILE) )
  370.                     {
  371.                         if( SystemTags(cmd, SYS_Input,  inf,
  372.                                             SYS_Output, tf,
  373.                                             TAG_DONE) == 0 )
  374.                         {
  375.                             STRPTR verbuf;
  376.                             
  377.                             /* Version command successful, alloc verbuf */
  378.                             if( verbuf = AllocVec(VERBUF_SIZE, 0) )
  379.                             {
  380.                                 /* Seek to start */
  381.                                 Seek(tf, 0, OFFSET_BEGINNING);
  382.                                 
  383.                                 /* Read first line */
  384.                                 if( FGets(tf, verbuf, VERBUF_SIZE-1) )
  385.                                 {
  386.                                     STRPTR s;
  387.                                     LONG state = STATE_NAME;
  388.                                     
  389.                                     /* Remove trailing EOL */
  390.                                     if( s = strchr(verbuf, '\n') )
  391.                                         *s = '\0';
  392.                                     
  393.                                     if( !full )
  394.                                     {
  395.                                         for( s = verbuf; *s ; ++s )
  396.                                         {
  397.                                             switch( state )
  398.                                             {
  399.                                                 case STATE_NAME :
  400.                                                     if( isspace(*s) )
  401.                                                     {
  402.                                                         state++;
  403.                                                         if( (!noname && !nover) ||
  404.                                                             (!noname && nover && !nodate) )
  405.                                                             FPutC(destf, ' ');
  406.                                                         s = stpblk(s);
  407.                                                         --s;
  408.                                                     } else
  409.                                                     {
  410.                                                         if( !noname )
  411.                                                             FPutC(destf, *s);
  412.                                                     }
  413.                                                     break;
  414.                                                 
  415.                                                 case STATE_VERSION :
  416.                                                     if( isspace(*s) )
  417.                                                     {
  418.                                                         state++;
  419.                                                         if( !nover && !nodate )
  420.                                                             FPutC(destf, ' ');
  421.                                                         s = stpblk(s);
  422.                                                         --s;
  423.                                                     } else
  424.                                                     {
  425.                                                         if( !nover )
  426.                                                             FPutC(destf, *s);
  427.                                                     }
  428.                                                     break;
  429.                                                 
  430.                                                 case STATE_DATE :
  431.                                                     if( !nodate )
  432.                                                     {
  433.                                                         if( noparsedate )
  434.                                                             FPutC(destf, *s);
  435.                                                         else
  436.                                                             if( (*s != '(') && (*s != ')') )
  437.                                                                 FPutC(destf, *s);
  438.                                                     }
  439.                                                     break;
  440.                                             }
  441.                                         }
  442.                                     } else
  443.                                         FPuts(destf, verbuf);
  444.                                 }
  445.                                 FreeVec(verbuf);
  446.                             }
  447.                         } else
  448.                             PrintFault(IoErr(), from);
  449.                         Close(inf);
  450.                     }
  451.                     Close(tf);
  452.                     DeleteFile(tmpname);
  453.                 }
  454.             }
  455.             FreeVec(tmpname);
  456.         }
  457.         FreeVec(cmd);
  458.     }
  459. }
  460.  
  461.  
  462. /*************************************************************************
  463.  * HProgramCmd() - Handle the PROGRAM command.
  464.  */
  465.  
  466.  
  467. VOID HProgramCmd(struct Vars *vars, BPTR destf, STRPTR cmdline, BOOL noline)
  468. {
  469.     STRPTR tmpname;
  470.     
  471.     /* Alloc tmpname */
  472.     if( tmpname = AllocVec(14, 0) )
  473.     {
  474.         strcpy(tmpname, TMP_TEMP);
  475.         mktemp(tmpname);
  476.         if( *tmpname != 0 )
  477.         {
  478.             BPTR tf;
  479.                 
  480.             /* Open temp file */
  481.             if( tf = Open(tmpname, MODE_NEWFILE) )
  482.             {
  483.                 
  484.                 if( SystemTags(cmdline, SYS_Output, tf, TAG_END) == 0 )
  485.                 {
  486.                     Close(tf);
  487.                     tf = 0;
  488.                     /* Recurse */
  489.                     RepMarkers(vars, tmpname, destf, noline);
  490.                 } else
  491.                     PrintFault(IoErr(), cmdline);
  492.  
  493.                 if( tf )
  494.                     Close(tf);
  495.                 DeleteFile(tmpname);
  496.             }
  497.         }
  498.         FreeVec(tmpname);
  499.     }
  500. }
  501.  
  502.  
  503. /*************************************************************************
  504.  * LFFunc() - Hook function for use in HDateCmd() by FormatDate().
  505.  */
  506.  
  507. /* 
  508.  * NOTE: no __saveds keyword, we dont need it and it would make us unpure
  509.  */
  510. ULONG __asm LFFunc(register __a0 struct Hook *hook,
  511.                    register __a2 struct Locale *locale,
  512.                    register __a1 char ch)
  513. {
  514.     /* hook->h_Data contains a BPTR of the file to output to */
  515.     if( ch )
  516.         FPutC((BPTR)hook->h_Data, ch);
  517.     return( TRUE );
  518. }
  519.  
  520.  
  521. /*************************************************************************
  522.  * HDateCmd() - Handle the DATE command.
  523.  */
  524.  
  525. VOID HDateCmd(struct Vars *vars, BPTR destf, STRPTR from, STRPTR localeformat, LONG format, 
  526.               BOOL noday, BOOL nodate, BOOL notime)
  527. {
  528.     struct DateStamp *ds = NULL;
  529.     
  530.     /* Get the datestamp */
  531.     if( from )
  532.     {
  533.         BPTR l;
  534.         
  535.         /* Read it from a file */
  536.         if( l = Lock(from, ACCESS_READ) )
  537.         {
  538.             struct FileInfoBlock *fib;
  539.             
  540.             /* Alloc fib */
  541.             if( fib = AllocDosObject(DOS_FIB, NULL) )
  542.             {
  543.                 if( Examine(l, fib) )
  544.                 {
  545.                     if( ds = AllocVec(sizeof(struct DateStamp), 0) )
  546.                     {
  547.                         /* Copy ds from the fib */
  548.                         memcpy(ds, &fib->fib_Date, sizeof(struct DateStamp));
  549.                     }
  550.                 }
  551.                 FreeDosObject(DOS_FIB, fib);
  552.             }
  553.             UnLock(l);
  554.         } else
  555.             PrintFault(IoErr(), from);
  556.     } else
  557.     {
  558.         if( ds = AllocVec(sizeof(struct DateStamp), 0) )
  559.             ds = DateStamp(ds);
  560.     }
  561.     if( ds )
  562.     {
  563.         /* Are we going to be locale or dos function based? */
  564.         if( localeformat && vars->v_Locale )
  565.         {
  566.             struct Hook *LFHook;
  567.             
  568.             if( LFHook = AllocVec(sizeof(struct Hook), MEMF_CLEAR) )
  569.             {
  570.                 LFHook->h_Entry    = (HOOKFUNC)LFFunc;
  571.                 
  572.                 /* Pass the file handle */
  573.                 LFHook->h_Data = (APTR)destf;
  574.                 
  575.                 FormatDate(vars->v_Locale, localeformat, ds, LFHook);
  576.                 FreeVec(LFHook);
  577.             }
  578.         } else
  579.         {
  580.             unsigned char daystr[LEN_DATSTRING], datestr[LEN_DATSTRING], timestr[LEN_DATSTRING];
  581.             struct DateTime *dt;
  582.             
  583.             if( dt = AllocVec(sizeof(struct DateTime), MEMF_CLEAR) )
  584.             {
  585.                 memcpy(&dt->dat_Stamp, ds, sizeof(struct DateStamp));
  586.                 dt->dat_Format = format;
  587.                 dt->dat_StrDay = (STRPTR)&daystr;
  588.                 dt->dat_StrDate = (STRPTR)&datestr;
  589.                 dt->dat_StrTime = (STRPTR)×tr;
  590.                 if( DateToStr(dt) )
  591.                 {
  592.                     if( !noday )
  593.                     {
  594.                         FPuts(destf, dt->dat_StrDay);
  595.                         if( !nodate || (nodate && !notime) )
  596.                             FPutC(destf, ' ');
  597.                     }
  598.                     
  599.                     if( !nodate )
  600.                     {
  601.                         FPuts(destf, dt->dat_StrDate);
  602.                         if( !notime )
  603.                             FPutC(destf, ' ');
  604.                     }
  605.                     
  606.                     if( !notime )
  607.                         FPuts(destf, dt->dat_StrTime);    
  608.                 }
  609.                 FreeVec(dt);
  610.             }
  611.         }
  612.         FreeVec(ds);
  613.     }
  614. }
  615.  
  616.  
  617. /*************************************************************************
  618.  * HVarCmd() - Handle the VAR command.
  619.  */
  620.  
  621. #define VAR_BUFFER_SIZE 512
  622.  
  623. VOID HVarCmd(BPTR destf, STRPTR from, BOOL newline, BOOL global, BOOL local)
  624. {
  625.     STRPTR buffer;
  626.     
  627.     /* Alloc buffer */
  628.     if( buffer = AllocVec(VAR_BUFFER_SIZE, 0) )
  629.     {
  630.         ULONG flags = LV_VAR;
  631.         
  632.         if( global )
  633.             flags |= GVF_GLOBAL_ONLY;
  634.         else if( local )
  635.             flags |= GVF_LOCAL_ONLY;
  636.         
  637.         if( GetVar(from, buffer, VAR_BUFFER_SIZE, flags) != -1 )
  638.         {
  639.             FPuts(destf, buffer);
  640.             if( newline )
  641.                 FPutC(destf, '\n');
  642.         } else
  643.             PrintFault(IoErr(), from);
  644.         FreeVec(buffer);
  645.     }
  646. }
  647.  
  648.  
  649. /*************************************************************************
  650.  * HSetvarCmd() - Handle the SETVAR command.
  651.  */
  652.  
  653. VOID HSetvarCmd(STRPTR name, STRPTR text)
  654. {
  655.     SetVar(name, text, -1, LV_VAR | GVF_LOCAL_ONLY);
  656. }
  657.  
  658. /*************************************************************************
  659.  * HTagCmd() - Handle the TAG command.
  660.  */
  661.  
  662. #define TAGBUF_SIZE 4096
  663.  
  664. VOID HTagCmd(struct Vars *vars, BPTR destf, STRPTR tag, STRPTR from, BOOL nonlcut)
  665. {
  666.     STRPTR stag;
  667.     
  668.     if( (tag) &&
  669.         (stag = AllocVec(strlen(tag)+4, MEMF_CLEAR)) )
  670.     {
  671.         BPTR f;
  672.         
  673.         strcpy(stag, "$: ");
  674.         strins(++stag, tag);
  675.         --stag;
  676.         
  677.         /* Open the source file */
  678.         if( f = Open(from, MODE_OLDFILE) )
  679.         {
  680.             LONG i, ch;
  681.             BOOL found = FALSE;
  682.             
  683.             /* Change buffer */
  684.             SetVBuf(f, NULL, vars->v_BufSize, BUF_FULL);
  685.             
  686.             for( ch = FGetC(f), i = 0; (ch != -1) && (!found); ch = FGetC(f) )
  687.                 if( ch == stag[i] )
  688.                     if( stag[i+1] == 0 )
  689.                         found = TRUE;
  690.                     else
  691.                         ++i;
  692.                 else
  693.                     i = 0;
  694.                     
  695.             if( found )
  696.                 for( ;
  697.                      (ch != -1) && (ch != '\0') && ( ((ch != '\r') && (ch != '\n')) || nonlcut);
  698.                      ch = FGetC(f)
  699.                    )
  700.                     if( ch != '\r' )
  701.                         FPutC(destf, ch);
  702.             
  703.             Close(f);
  704.         }
  705.         FreeVec(stag);
  706.     }
  707. }
  708.  
  709.  
  710. /*************************************************************************
  711.  * RepMarkers() - Parse a file and replace 'stuff'
  712.  */
  713.  
  714. /* Command introducors and terminators */
  715. #define INTRODUCER_1 '/'
  716. #define INTRODUCER_2 '>'  /* INTRODUCER = "/>" */
  717. #define TERMINATOR_1 '<'
  718. #define TERMINATOR_2 '\\' /* TERMINATOR = "<\" */
  719. #define ESCAPE_CHAR  '!'
  720.  
  721. /* When read thru a line char by char we can by in any of these states */
  722. #define LEV_ESCAPED_2 -2
  723. #define LEV_ESCAPED_1 -1
  724. #define LEV_NONE 0
  725. #define LEV_1 1
  726. #define LEV_2 2
  727. #define LEV_3 3
  728.  
  729. #define BUFFER_SIZE 256
  730.  
  731. #define CMD_BUF_SIZE strlen(buffer)+2
  732.  
  733. VOID RepMarkers(struct Vars *vars, STRPTR source, BPTR destf, BOOL nolines)
  734. {
  735.     BPTR sourcef;
  736.     
  737.     /* Open source file */
  738.     if( sourcef = Open(source, MODE_OLDFILE) )
  739.     {
  740.         APTR buf;
  741.         
  742.         /* Change buffer */
  743.         SetVBuf(sourcef, NULL, vars->v_BufSize, BUF_FULL); 
  744.  
  745.             
  746.         /* Alloc buf */
  747.         if( buf = AllocVec(BUFFER_SIZE, 0) )
  748.         {
  749.             APTR buffer;
  750.             
  751.             /* Go thru the source file, line by line */
  752.             while( buffer = FGets(sourcef, buf, BUFFER_SIZE-1) )
  753.             {
  754.                 STRPTR cmd;
  755.                 
  756.                 /* Alloc cmd buffer.
  757.                  * strlen(buffer)+2, 1 extra for the null and 1 more cause we add
  758.                  * on a '\n' in HInsertion()
  759.                  */
  760.                 if( cmd = AllocVec(CMD_BUF_SIZE, MEMF_CLEAR) )
  761.                 {
  762.                     register STRPTR s;
  763.                     register LONG level = LEV_NONE;
  764.                     /*
  765.                      * For each line we parse each character in a
  766.                      * state machine manner.
  767.                      */
  768.                     for( s = buffer; *s ; ++s )
  769.                     {
  770.                         switch( level )
  771.                         {
  772.                             case LEV_ESCAPED_1 :
  773.                                 switch( *s )
  774.                                 {
  775.                                     case INTRODUCER_1 :
  776.                                         level = LEV_ESCAPED_2;
  777.                                         break;
  778.                                     
  779.                                     case ESCAPE_CHAR :
  780.                                         level = LEV_ESCAPED_1;
  781.                                         FPutC(destf, (LONG)ESCAPE_CHAR);
  782.                                         break;
  783.                                     
  784.                                     default:
  785.                                         level = LEV_NONE;
  786.                                         FPutC(destf, (LONG)ESCAPE_CHAR);
  787.                                         MFPutC(destf, (LONG)*s, nolines);
  788.                                         break;
  789.                                 }
  790.                                 break;
  791.                                                             
  792.                             case LEV_ESCAPED_2 :
  793.                                 if( *s == INTRODUCER_2 )
  794.                                 {
  795.                                     FPutC(destf, (LONG)INTRODUCER_1);
  796.                                     FPutC(destf, (LONG)INTRODUCER_2);
  797.                                     ++vars->v_Tags_e;
  798.                                 } else
  799.                                 {
  800.                                     FPutC(destf, (LONG)ESCAPE_CHAR);
  801.                                     FPutC(destf, (LONG)INTRODUCER_1);
  802.                                     MFPutC(destf, (LONG)*s, nolines);
  803.                                 }
  804.                                 level = LEV_NONE;
  805.                                 break;
  806.                                 
  807.                             case LEV_NONE :
  808.                                 switch( *s )
  809.                                 {
  810.                                     case INTRODUCER_1 :
  811.                                         level = LEV_1;
  812.                                         break;
  813.                                     case ESCAPE_CHAR :
  814.                                         level = LEV_ESCAPED_1;
  815.                                         break;
  816.                                     default :
  817.                                         level = LEV_NONE;
  818.                                         MFPutC(destf, (LONG)*s, nolines);
  819.                                         break;
  820.                                 }
  821.                                 break;
  822.                                 
  823.                             case LEV_1 :
  824.                                 if( *s == INTRODUCER_2 )
  825.                                     level = LEV_2;
  826.                                 else
  827.                                 {
  828.                                     level = LEV_NONE;
  829.                                     FPutC(destf, (LONG)INTRODUCER_1);
  830.                                     MFPutC(destf, (LONG)*s, nolines);
  831.                                 }
  832.                                 break;
  833.                         
  834.                             case LEV_2 :
  835.                                 if( *s == TERMINATOR_1 )
  836.                                     level = LEV_3;
  837.                                 else
  838.                                     AddC2Cmd(cmd, *s);
  839.                                 break;
  840.                             
  841.                             case LEV_3 :
  842.                                 if( *s == TERMINATOR_2 )
  843.                                 {
  844.                                     level = LEV_NONE;
  845.                                     HInsertion(vars, destf, cmd, CMD_BUF_SIZE);
  846.                                 } else
  847.                                 {
  848.                                     level = LEV_2;
  849.                                     AddC2Cmd(cmd, TERMINATOR_1);
  850.                                     AddC2Cmd(cmd, *s);
  851.                                 }
  852.                                 break;
  853.                         }
  854.                     }
  855.                     /* Do insertion if cmd has something in it (ie non terminated cmd) */
  856.                     if( *cmd != '\0' )
  857.                     {
  858.                         HInsertion(vars, destf, cmd, CMD_BUF_SIZE);
  859.                         MFPutC(destf, '\n', nolines);
  860.                     }
  861.                     FreeVec(cmd);
  862.                 }
  863.             }                
  864.             FreeVec(buffer);
  865.         }
  866.         Close(sourcef);
  867.     } else
  868.         PrintFault(IoErr(), source);
  869. }
  870.  
  871.  
  872. /*************************************************************************
  873.  * main() - Ehhh... It's kinda ehhh...
  874.  */
  875.  
  876. int main( VOID )
  877. {
  878.     LONG rc = 10;
  879.     if( (((struct Library *)DOSBase)->lib_Version > 35) &&
  880.         (((struct Library *)SysBase)->lib_Version > 35) )
  881.     {
  882.         struct Vars *vars;
  883.         
  884.         /* Allocate var structure */
  885.         if( vars = AllocVec(sizeof(struct Vars), MEMF_CLEAR) )
  886.         {
  887.             struct RDArgs *rdargs;
  888.             #define TEMPLATE "SOURCE/A,DESTINATION,BUFFER/K/N,QUIET/S"
  889.             #define OPT_SOURCE 0
  890.             #define OPT_DEST 1
  891.             #define OPT_BUFFER 2
  892.             #define OPT_QUIET 3
  893.             #define OPT_MAX 4
  894.             #define DEF_BUFFER 16384
  895.             STRPTR args[OPT_MAX] = {0, 0, 0, 0};
  896.             #define ARG_SOURCE args[OPT_SOURCE]
  897.             STRPTR  ARG_DEST;
  898.             #define ARG_QUIET (BOOL)args[OPT_QUIET]
  899.         
  900.             /* Open Locale */
  901.             if( vars->v_LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library", 38) )
  902.                 vars->v_Locale = OpenLocale(NULL);
  903.             else
  904.                 vars->v_Locale = NULL;
  905.             LocaleBase = vars->v_LocaleBase;
  906.         
  907.             /* Parse arguments */
  908.             if (rdargs = ReadArgs(TEMPLATE, (LONG *)&args, NULL))
  909.             {
  910.                 BPTR srcl;
  911.                 
  912.                 ARG_DEST = args[OPT_DEST];
  913.                 
  914.                 if( args[OPT_BUFFER] )
  915.                     vars->v_BufSize = ((*((LONG *)args[OPT_BUFFER]) >= 208) ?
  916.                                          *((LONG *)args[OPT_BUFFER]) :
  917.                                          DEF_BUFFER);
  918.                 else
  919.                     vars->v_BufSize = DEF_BUFFER;
  920.                 
  921.                 /* Lock source */
  922.                 if( srcl = Lock(ARG_SOURCE, ACCESS_READ) )
  923.                 {
  924.                     BOOL makefilename = FALSE;
  925.                     BOOL destok = TRUE;
  926.                     
  927.                     if( ARG_DEST )
  928.                     {
  929.                         BPTR destl;
  930.                     
  931.                         /* Try to lock dest */
  932.                         if( destl = Lock(ARG_DEST, ACCESS_READ) )
  933.                         {
  934.                             /* Same file? */
  935.                             if( SameLock(srcl, destl) == LOCK_SAME )
  936.                             {
  937.                                 destok = FALSE;
  938.                                 SetIoErr(ERROR_OBJECT_EXISTS);
  939.                             }
  940.                             UnLock(destl);
  941.                         }
  942.                     } else
  943.                         makefilename = TRUE;
  944.                     
  945.                     if( makefilename )
  946.                     {
  947.                         /* Use a temp file */
  948.                         
  949.                         if( ARG_DEST = AllocVec(14, 0) )
  950.                         {
  951.                             strcpy(ARG_DEST, TMP_TEMP);
  952.                             mktemp(ARG_DEST);
  953.                             if( *ARG_DEST != 0 )
  954.                                 destok = TRUE;
  955.                         }
  956.                     }
  957.                     
  958.                     if( destok )
  959.                     {
  960.                         BPTR destf;
  961.                         if( destf = Open(ARG_DEST, MODE_NEWFILE) )
  962.                         {
  963.                             /* Change buffer */
  964.                             SetVBuf(destf, NULL, vars->v_BufSize, BUF_FULL);
  965.                             
  966.                             RepMarkers(vars, ARG_SOURCE, destf, FALSE);
  967.                             Close(destf);
  968.                             if( !ARG_QUIET )
  969.                             {
  970.                                 if( vars->v_Tags_p )
  971.                                     Printf("%ld tags processed\n", vars->v_Tags_p);
  972.                                 if( vars->v_Tags_e )
  973.                                     Printf("%ld tags escaped\n", vars->v_Tags_e);
  974.                                 if( vars->v_Tags_i )
  975.                                     Printf("%ld invalid tags\n", vars->v_Tags_i);
  976.                             }
  977.                             rc = 0;
  978.                         }
  979.                     }
  980.                     
  981.                     UnLock(srcl);
  982.                     
  983.                     if( makefilename )
  984.                     {
  985.                         if( rc == 0)
  986.                         {
  987.                             BPTR src;
  988.                             
  989.                             /* Copy ARG_DEST to ARG_SOURCE */
  990.                             
  991.                             if( src    = Open(ARG_DEST, MODE_OLDFILE) )
  992.                             {
  993.                                 BPTR dest;
  994.                                 
  995.                                 if( dest = Open(ARG_SOURCE, MODE_NEWFILE) )
  996.                                 {
  997.                                     LONG ch;
  998.                                     
  999.                                     for( ch = FGetC(src); ch != -1; ch = FGetC(src) )
  1000.                                         FPutC(dest, ch);
  1001.                                     
  1002.                                     Close(dest);
  1003.                                 }
  1004.                                 Close(src);
  1005.                             }
  1006.                         }
  1007.                         
  1008.                         /* Delete the temp file */
  1009.                         DeleteFile(ARG_DEST);
  1010.                         
  1011.                         /* Free name buffer */
  1012.                         FreeVec(ARG_DEST);
  1013.                     }
  1014.  
  1015.                 }
  1016.                 FreeArgs(rdargs);
  1017.             }
  1018.         
  1019.             if( vars->v_Locale )
  1020.                 CloseLocale(vars->v_Locale);
  1021.                 
  1022.             if( vars->v_LocaleBase )
  1023.                 CloseLibrary((struct Library *)vars->v_LocaleBase);
  1024.             
  1025.             FreeVec(vars);
  1026.         }
  1027.     }
  1028.     if( rc )
  1029.         PrintFault(IoErr(), "Umentiler");
  1030.     return( rc );
  1031. }
  1032.